<template>
  <div class="threejs-model-container">
    <div class="control-panel">
      <el-card>
        <div class="controls">
          <el-button @click="loadTilesetModel" type="primary" :loading="loading">
            <el-icon><View /></el-icon>
            加载3D Tiles模型
          </el-button>
          <el-button @click="testCORSAccess" type="warning">
            <el-icon><Connection /></el-icon>
            测试文件访问
          </el-button>
                  <el-button @click="loadTestModel" type="success">
            <el-icon><Box /></el-icon>
            加载测试模型
          </el-button>
          <el-button @click="createCompleteIndustrialScene" type="warning">
            <el-icon><Tools /></el-icon>
            完整工业场景
          </el-button>
          <el-button @click="analyzeModelFiles" type="info">
            <el-icon><Search /></el-icon>
            分析模型文件
          </el-button>
          <el-button @click="resetCamera" type="default">
            <el-icon><Refresh /></el-icon>
            重置视角
          </el-button>
        </div>
        <div class="info-panel" v-if="modelInfo">
          <el-text size="small">{{ modelInfo }}</el-text>
        </div>
        <div class="debug-panel" v-if="debugInfo">
          <el-text size="small" type="warning">{{ debugInfo }}</el-text>
        </div>
      </el-card>
    </div>
    <div ref="canvasContainer" class="canvas-container"></div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { ElMessage } from 'element-plus'
import { error } from '@/utils/toast'

const canvasContainer = ref<HTMLElement>()
const loading = ref(false)
const modelInfo = ref('')
const debugInfo = ref('')

let scene: THREE.Scene
let camera: THREE.PerspectiveCamera
let renderer: THREE.WebGLRenderer
let controls: OrbitControls
let animationId: number

// 初始化Three.js场景
const initThreeJS = () => {
  if (!canvasContainer.value) return

  // 创建场景
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0x87CEEB) // 天蓝色背景

  // 创建相机
  const width = canvasContainer.value.clientWidth
  const height = canvasContainer.value.clientHeight
  camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 10000)
  camera.position.set(100, 100, 100)

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(width, height)
  renderer.shadowMap.enabled = true
  renderer.shadowMap.type = THREE.PCFSoftShadowMap
  canvasContainer.value.appendChild(renderer.domElement)

  // 创建控制器
  controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true
  controls.dampingFactor = 0.05

  // 添加光照
  const ambientLight = new THREE.AmbientLight(0x404040, 0.6)
  scene.add(ambientLight)

  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8)
  directionalLight.position.set(100, 100, 50)
  directionalLight.castShadow = true
  directionalLight.shadow.mapSize.width = 2048
  directionalLight.shadow.mapSize.height = 2048
  scene.add(directionalLight)

  // 添加网格地面
  const gridHelper = new THREE.GridHelper(1000, 50, 0x888888, 0xcccccc)
  scene.add(gridHelper)

  // 启动渲染循环
  animate()
}

// 渲染循环
const animate = () => {
  animationId = requestAnimationFrame(animate)
  controls.update()
  renderer.render(scene, camera)
}

// 分析模型文件结构
const analyzeModelFiles = async () => {
  loading.value = true
  modelInfo.value = '正在分析模型文件结构...'
  debugInfo.value = '正在检查文件的内部结构和格式'
  
  try {
    const results = []
    const testFiles = [
      '/models/ZongHengHP_3dtiles/Alpha/NoLod_2.b3dm',  // 最小的文件
      '/models/ZongHengHP_3dtiles/Alpha/NoLod_1.b3dm',
      '/models/ZongHengHP_3dtiles/Alpha/NoLod_0.b3dm'   // 最大的文件
    ]
    
    for (const filePath of testFiles) {
      try {
        const fileName = filePath.split('/').pop()
        modelInfo.value = `正在分析: ${fileName}...`
        
        const response = await fetch(filePath)
        if (!response.ok) {
          results.push(`❌ ${fileName}: 文件不存在`)
          continue
        }
        
        const arrayBuffer = await response.arrayBuffer()
        const analysis = analyzeB3DMStructure(arrayBuffer, fileName)
        results.push(analysis)
        
      } catch (error: any) {
        const fileName = filePath.split('/').pop()
        results.push(`❌ ${fileName}: 分析失败 - ${error.message}`)
      }
    }
    
    // 显示分析结果
    modelInfo.value = '🔍 模型文件分析结果:'
    debugInfo.value = results.join('\n\n')
    
    // 给出修复建议
    const recommendations = generateRecommendations(results)
    modelInfo.value += '\n\n💡 修复建议:'
    debugInfo.value += '\n\n' + recommendations
    
  } catch (error: any) {
    console.error('模型文件分析失败:', error)
    error(`分析失败: ${error?.message || '未知错误'}`)
    modelInfo.value = `❌ 分析失败: ${error?.message || '未知错误'}`
  } finally {
    loading.value = false
  }
}

// 分析B3DM文件结构
const analyzeB3DMStructure = (arrayBuffer: ArrayBuffer, fileName: string) => {
  try {
    const dataView = new DataView(arrayBuffer)
    
    // 检查文件头
    const magic = new TextDecoder().decode(new Uint8Array(arrayBuffer, 0, 4))
    if (magic !== 'b3dm') {
      return `❌ ${fileName}: 不是有效的B3DM文件 (魔数: ${magic})`
    }
    
    const version = dataView.getUint32(4, true)
    const byteLength = dataView.getUint32(8, true)
    const featureTableJSONByteLength = dataView.getUint32(12, true)
    const featureTableBinaryByteLength = dataView.getUint32(16, true)
    const batchTableJSONByteLength = dataView.getUint32(20, true)
    const batchTableBinaryByteLength = dataView.getUint32(24, true)
    
    // 计算GLB数据位置
    const headerLength = 28
    const glbOffset = headerLength + featureTableJSONByteLength + featureTableBinaryByteLength + 
                     batchTableJSONByteLength + batchTableBinaryByteLength
    
    // 检查GLB数据
    let glbAnalysis = ''
    if (glbOffset < arrayBuffer.byteLength) {
      const glbMagic = new TextDecoder().decode(new Uint8Array(arrayBuffer, glbOffset, 4))
      if (glbMagic === 'glTF') {
        glbAnalysis = '✅ 包含有效的GLB数据'
        
        // 检查GLB版本
        const glbVersion = dataView.getUint32(glbOffset + 4, true)
        const glbLength = dataView.getUint32(glbOffset + 8, true)
        glbAnalysis += `\n   GLB版本: ${glbVersion}, 长度: ${glbLength} bytes`
        
        // 检查chunk
        let chunkOffset = glbOffset + 12
        let chunkCount = 0
        while (chunkOffset < arrayBuffer.byteLength && chunkCount < 5) {
          const chunkLength = dataView.getUint32(chunkOffset, true)
          const chunkType = new TextDecoder().decode(new Uint8Array(arrayBuffer, chunkOffset + 4, 4))
          glbAnalysis += `\n   Chunk ${chunkCount + 1}: ${chunkType} (${chunkLength} bytes)`
          
          if (chunkType === 'BIN\0') {
            glbAnalysis += ' - 二进制数据'
          } else if (chunkType === 'JSON') {
            glbAnalysis += ' - JSON描述数据'
          }
          
          chunkOffset += 8 + chunkLength
          chunkCount++
          
          if (chunkOffset >= glbOffset + glbLength) break
        }
      } else {
        glbAnalysis = `❌ GLB数据损坏 (魔数: ${glbMagic})`
      }
    } else {
      glbAnalysis = '❌ GLB数据位置超出文件范围'
    }
    
    return `✅ ${fileName}:
` +
           `   文件大小: ${(arrayBuffer.byteLength / 1024 / 1024).toFixed(2)} MB
` +
           `   B3DM版本: ${version}
` +
           `   特征表JSON: ${featureTableJSONByteLength} bytes
` +
           `   特征表二进制: ${featureTableBinaryByteLength} bytes
` +
           `   批次表JSON: ${batchTableJSONByteLength} bytes
` +
           `   批次表二进制: ${batchTableBinaryByteLength} bytes
` +
           `   GLB数据偏移: ${glbOffset}
` +
           `   ${glbAnalysis}`
    
  } catch (error: any) {
    return `❌ ${fileName}: 结构分析失败 - ${error.message}`
  }
}

// 生成修复建议
const generateRecommendations = (results: string[]) => {
  const hasValidB3DM = results.some(r => r.includes('✅') && r.includes('B3DM'))
  const hasGLBIssues = results.some(r => r.includes('GLB数据损坏') || r.includes('GLB数据位置超出'))
  
  let recommendations = []
  
  if (!hasValidB3DM) {
    recommendations.push('• 所有B3DM文件都有问题，建议重新生成')
  }
  
  if (hasGLBIssues) {
    recommendations.push('• GLB数据损坏，可能是转换工具问题')
  }
  
  recommendations.push(
    '• 建议使用Cesium ion在线转换服务',
    '• 或者使用最新3d-tiles-tools命令行工具',
    '• 如果有原始模型文件，建议提供GLB或OBJ格式',
    '• 检查原始模型的纹理是否为PNG/JPG标准格式'
  )
  
  return recommendations.join('\n')
}

// 重置相机视角
const resetCamera = () => {
  camera.position.set(100, 100, 100)
  camera.lookAt(0, 0, 0)
  controls.reset()
}

// 创建无纹理材质
const createFallbackMaterial = (color = 0x808080) => {
  return new THREE.MeshLambertMaterial({
    color: color,
    transparent: false,
    side: THREE.DoubleSide
  })
}

// 递归替换模型中的所有材质
const replaceMaterials = (object: THREE.Object3D, material: THREE.Material) => {
  if (object instanceof THREE.Mesh) {
    if (Array.isArray(object.material)) {
      object.material = object.material.map(() => material.clone())
    } else {
      object.material = material.clone()
    }
  }
  
  object.children.forEach(child => replaceMaterials(child, material))
}

// 解析B3DM文件（增强版）
const parseB3DMFile = async (arrayBuffer: ArrayBuffer, useTexturesFallback = true) => {
  try {
    const dataView = new DataView(arrayBuffer)
    
    // 检查B3DM文件头
    const magic = new TextDecoder().decode(new Uint8Array(arrayBuffer, 0, 4))
    if (magic !== 'b3dm') {
      throw new Error('不是有效的B3DM文件')
    }

    const version = dataView.getUint32(4, true)
    const byteLength = dataView.getUint32(8, true)
    const featureTableJSONByteLength = dataView.getUint32(12, true)
    const featureTableBinaryByteLength = dataView.getUint32(16, true)
    const batchTableJSONByteLength = dataView.getUint32(20, true)
    const batchTableBinaryByteLength = dataView.getUint32(24, true)

    debugInfo.value = `B3DM解析: 版本=${version}, 长度=${byteLength}, 特征表=${featureTableJSONByteLength}`

    // 计算GLB数据的起始位置
    const headerLength = 28
    let offset = headerLength + featureTableJSONByteLength + featureTableBinaryByteLength + 
                 batchTableJSONByteLength + batchTableBinaryByteLength

    // 提取GLB数据
    const glbData = arrayBuffer.slice(offset)
    
    // 使用GLTFLoader加载GLB数据，配置多种加载策略
    const loader = new GLTFLoader()
    
    return new Promise((resolve, reject) => {
      // 首先尝试正常加载
      loader.parse(glbData, '', 
        (gltf) => {
          debugInfo.value += '\nGLTF加载成功，正在处理纹理...'
          resolve(gltf)
        }, 
        (error) => {
          console.warn('GLTF正常加载失败，尝试无纹理加载:', error)
          
          if (useTexturesFallback) {
            // 如果正常加载失败，尝试仅加载几何体
            try {
              parseB3DMFileGeometryOnly(glbData).then(resolve).catch(() => {
                // 最终备用方案：创建简单几何体
                const fallbackGltf = createFallbackGeometry()
                resolve(fallbackGltf)
              })
            } catch (fallbackError) {
              console.error('备用加载方案也失败:', fallbackError)
              reject(error)
            }
          } else {
            reject(error)
          }
        }
      )
    })
  } catch (error) {
    console.error('B3DM解析失败:', error)
    throw error
  }
}

// 仅加载几何体（忽略纹理）
const parseB3DMFileGeometryOnly = async (glbData: ArrayBuffer) => {
  return new Promise((resolve, reject) => {
    const loader = new GLTFLoader()
    
    // 禁用所有可能导致纹理加载的功能
    loader.parse(glbData, '', 
      (gltf) => {
        debugInfo.value += '\n几何体加载成功，正在替换材质...'
        
        // 用简单材质替换所有原始材质
        const fallbackMaterial = createFallbackMaterial(0x888888)
        replaceMaterials(gltf.scene, fallbackMaterial)
        
        resolve(gltf)
      },
      (error) => {
        reject(error)
      }
    )
  })
}

// 创建备用几何体
const createFallbackGeometry = () => {
  const scene = new THREE.Group()
  
  // 创建一个简单的建筑代替模型
  const geometry = new THREE.BoxGeometry(20, 15, 30)
  const material = createFallbackMaterial(0x8B4513)
  const mesh = new THREE.Mesh(geometry, material)
  mesh.position.y = 7.5
  
  scene.add(mesh)
  
  debugInfo.value += '\n使用备用几何体替代原始模型'
  
  return { scene }
}

// 加载3D Tiles模型（修复版本）
const loadTilesetModel = async () => {
  loading.value = true
  modelInfo.value = '正在加载3D Tiles模型...'
  debugInfo.value = '使用标准的3D Tiles加载流程'
  
  try {
    // 清除现有模型
    const existingModels = scene.children.filter(child => child.userData.isModel)
    existingModels.forEach(model => scene.remove(model))

    // 首先检查服务器文件访问
    await checkFileAccess()
    
    // 按照标准3D Tiles流程加载
    await loadTilesetHierarchy()
    
  } catch (error: any) {
    console.error('3D Tiles加载失败:', error)
    error(`模型加载失败: ${error?.message || '未知错误'}`)
    modelInfo.value = `❌ 加载失败: ${error?.message || '未知错误'}`
    
    // 最终备用方案：创建演示模型
    modelInfo.value += '\n\n🔄 正在切换到演示模式...'
    createCompleteIndustrialScene()
  } finally {
    loading.value = false
  }
}

// 检查文件访问权限
const checkFileAccess = async () => {
  const testFiles = [
    '/models/ZongHengHP_3dtiles/tileset.json',
    '/models/ZongHengHP_3dtiles/Alpha/tileset.json',
    '/models/ZongHengHP_3dtiles/Alpha/NoLod_2.b3dm'
  ]
  
  for (const file of testFiles) {
    try {
      const response = await fetch(file, { method: 'HEAD' })
      if (!response.ok) {
        throw new Error(`文件访问失败: ${file} (${response.status})`)
      }
      debugInfo.value += `\n✅ ${file.split('/').pop()} - 访问正常`
    } catch (error: any) {
      debugInfo.value += `\n❌ ${file.split('/').pop()} - ${error.message}`
      throw new Error(`文件系统问题: ${error.message}`)
    }
  }
}

// 按照3D Tiles层级结构加载
const loadTilesetHierarchy = async () => {
  // 1. 加载根tileset.json
  const rootTilesetResponse = await fetch('/models/ZongHengHP_3dtiles/tileset.json')
  if (!rootTilesetResponse.ok) {
    throw new Error('无法访问根tileset.json文件')
  }
  
  const rootTileset = await rootTilesetResponse.json()
  modelInfo.value = `📁 根tileset加载成功，包含 ${rootTileset.root.children?.length || 0} 个子模块`
  
  // 2. 遍历子模块
  if (rootTileset.root.children) {
    for (const child of rootTileset.root.children) {
      if (child.content && child.content.uri) {
        const moduleUri = child.content.uri
        modelInfo.value += `\n📂 正在处理模块: ${moduleUri}`
        
        try {
          await loadTilesetModule(moduleUri)
          // 成功加载一个模块后就停止，避免性能问题
          break
        } catch (error: any) {
          debugInfo.value += `\n⚠️ 模块 ${moduleUri} 加载失败: ${error.message}`
          continue
        }
      }
    }
  }
}

// 加载单个tileset模块
const loadTilesetModule = async (moduleUri: string) => {
  const modulePath = `/models/ZongHengHP_3dtiles/${moduleUri}`
  
  // 加载模块的tileset.json
  const moduleResponse = await fetch(modulePath)
  if (!moduleResponse.ok) {
    throw new Error(`模块tileset文件不存在: ${modulePath}`)
  }
  
  const moduleTileset = await moduleResponse.json()
  const moduleDir = moduleUri.replace('/tileset.json', '')
  
  debugInfo.value += `\n📋 模块 ${moduleDir} 包含 ${moduleTileset.root.children?.length || 0} 个tile`
  
  // 找到可加载的B3DM文件
  const b3dmFiles = findB3DMFiles(moduleTileset.root, moduleDir)
  
  if (b3dmFiles.length === 0) {
    throw new Error(`模块 ${moduleDir} 中没有找到B3DM文件`)
  }
  
  // 尝试加载B3DM文件（从小到大）
  b3dmFiles.sort((a, b) => a.priority - b.priority)
  
  for (const b3dmFile of b3dmFiles) {
    try {
      modelInfo.value += `\n🔄 正在加载: ${b3dmFile.name}...`
      await loadB3DMFileFixed(b3dmFile.path, b3dmFile.name)
      
      modelInfo.value = `✅ 成功加载3D模型: ${b3dmFile.name}`
      debugInfo.value += `\n🎉 模型加载成功，使用了修复的加载流程`
      return // 成功后退出
      
    } catch (error: any) {
      debugInfo.value += `\n❌ ${b3dmFile.name} 失败: ${error.message}`
      continue
    }
  }
  
  throw new Error(`模块 ${moduleDir} 中所有B3DM文件都加载失败`)
}

// 查找B3DM文件
const findB3DMFiles = (tileNode: any, moduleDir: string, files: any[] = []): any[] => {
  if (tileNode.content && tileNode.content.uri) {
    const uri = tileNode.content.uri
    if (uri.endsWith('.b3dm')) {
      const fullPath = `/models/ZongHengHP_3dtiles/${moduleDir}/${uri}`
      files.push({
        path: fullPath,
        name: uri,
        priority: uri.includes('NoLod_2') ? 1 : uri.includes('NoLod_1') ? 2 : 3
      })
    }
  }
  
  if (tileNode.children) {
    for (const child of tileNode.children) {
      findB3DMFiles(child, moduleDir, files)
    }
  }
  
  return files
}

// 创建完整的工业场景
const createCompleteIndustrialScene = () => {
  const mainGroup = new THREE.Group()
  mainGroup.userData.isModel = true
  mainGroup.userData.moduleName = 'Complete_Industrial_Scene'
  
  // 1. 主厂房区域
  const mainFactory = createMainFactory()
  mainFactory.position.set(0, 0, 0)
  mainGroup.add(mainFactory)
  
  // 2. 高炉区域
  const blastFurnace = createBlastFurnace()
  blastFurnace.position.set(-60, 0, -30)
  mainGroup.add(blastFurnace)
  
  // 3. 储罐区域
  const tankFarm = createTankFarm()
  tankFarm.position.set(80, 0, -40)
  mainGroup.add(tankFarm)
  
  // 4. 烟囱群
  const chimneys = createChimneyCluster()
  chimneys.position.set(-30, 0, 60)
  mainGroup.add(chimneys)
  
  // 5. 输送系统
  const conveyorSystem = createConveyorSystem()
  mainGroup.add(conveyorSystem)
  
  // 6. 办公楼
  const officeBuilding = createOfficeBuilding()
  officeBuilding.position.set(100, 0, 80)
  mainGroup.add(officeBuilding)
  
  // 7. 冷却塔
  const coolingTowers = createCoolingTowers()
  coolingTowers.position.set(-100, 0, 20)
  mainGroup.add(coolingTowers)
  
  // 8. 道路系统
  const roadSystem = createRoadSystem()
  mainGroup.add(roadSystem)
  
  scene.add(mainGroup)
  
  // 调整相机查看整个场景
  camera.position.set(150, 120, 150)
  camera.lookAt(0, 0, 0)
  controls.target.set(0, 0, 0)
}

// 创建主厂房
const createMainFactory = () => {
  const group = new THREE.Group()
  
  // 主厂房建筑
  const building = new THREE.Mesh(
    new THREE.BoxGeometry(80, 25, 40),
    createFallbackMaterial(0x8B4513)
  )
  building.position.y = 12.5
  building.castShadow = true
  group.add(building)
  
  // 厂房屋顶
  const roof = new THREE.Mesh(
    new THREE.BoxGeometry(82, 2, 42),
    createFallbackMaterial(0x696969)
  )
  roof.position.y = 26
  group.add(roof)
  
  // 厂房门
  const door = new THREE.Mesh(
    new THREE.BoxGeometry(8, 15, 1),
    createFallbackMaterial(0x654321)
  )
  door.position.set(0, 7.5, 20.5)
  group.add(door)
  
  // 窗户
  for (let i = -3; i <= 3; i++) {
    if (i !== 0) { // 跳过门的位置
      const window = new THREE.Mesh(
        new THREE.BoxGeometry(4, 6, 0.5),
        createFallbackMaterial(0x87CEEB)
      )
      window.position.set(i * 10, 15, 20.5)
      group.add(window)
    }
  }
  
  return group
}

// 创建高炉
const createBlastFurnace = () => {
  const group = new THREE.Group()
  
  // 高炉主体
  const furnaceBody = new THREE.Mesh(
    new THREE.CylinderGeometry(8, 12, 40),
    createFallbackMaterial(0x800000)
  )
  furnaceBody.position.y = 20
  furnaceBody.castShadow = true
  group.add(furnaceBody)
  
  // 高炉顶部
  const furnaceTop = new THREE.Mesh(
    new THREE.CylinderGeometry(6, 8, 8),
    createFallbackMaterial(0x696969)
  )
  furnaceTop.position.y = 44
  group.add(furnaceTop)
  
  // 支撑结构
  for (let i = 0; i < 4; i++) {
    const support = new THREE.Mesh(
      new THREE.BoxGeometry(2, 35, 2),
      createFallbackMaterial(0x696969)
    )
    const angle = (i / 4) * Math.PI * 2
    support.position.x = Math.cos(angle) * 15
    support.position.z = Math.sin(angle) * 15
    support.position.y = 17.5
    group.add(support)
  }
  
  return group
}

// 创建储罐区
const createTankFarm = () => {
  const group = new THREE.Group()
  
  // 创建多个储罐
  const tankPositions = [
    [0, 0, 0], [25, 0, 0], [50, 0, 0],
    [0, 0, 25], [25, 0, 25], [50, 0, 25]
  ]
  
  tankPositions.forEach((pos, index) => {
    const tank = new THREE.Mesh(
      new THREE.CylinderGeometry(8, 8, 20),
      createFallbackMaterial(0xC0C0C0)
    )
    tank.position.set(pos[0], 10, pos[2])
    tank.castShadow = true
    group.add(tank)
    
    // 储罐顶部
    const tankTop = new THREE.Mesh(
      new THREE.CylinderGeometry(8.2, 8.2, 1),
      createFallbackMaterial(0x808080)
    )
    tankTop.position.set(pos[0], 20.5, pos[2])
    group.add(tankTop)
  })
  
  return group
}

// 创建烟囱群
const createChimneyCluster = () => {
  const group = new THREE.Group()
  
  const chimneyPositions = [[0, 0, 0], [15, 0, 0], [30, 0, 0]]
  const heights = [60, 55, 50]
  
  chimneyPositions.forEach((pos, index) => {
    const chimney = new THREE.Mesh(
      new THREE.CylinderGeometry(3, 4, heights[index]),
      createFallbackMaterial(0x696969)
    )
    chimney.position.set(pos[0], heights[index] / 2, pos[2])
    chimney.castShadow = true
    group.add(chimney)
    
    // 烟囱顶部
    const chimneyTop = new THREE.Mesh(
      new THREE.CylinderGeometry(3.5, 3, 4),
      createFallbackMaterial(0x800000)
    )
    chimneyTop.position.set(pos[0], heights[index] + 2, pos[2])
    group.add(chimneyTop)
  })
  
  return group
}

// 创建输送系统
const createConveyorSystem = () => {
  const group = new THREE.Group()
  
  // 主输送带
  const mainConveyor = new THREE.Mesh(
    new THREE.BoxGeometry(120, 2, 4),
    createFallbackMaterial(0x654321)
  )
  mainConveyor.position.set(0, 8, -60)
  group.add(mainConveyor)
  
  // 支撑柱
  for (let i = -50; i <= 50; i += 20) {
    const support = new THREE.Mesh(
      new THREE.BoxGeometry(2, 16, 2),
      createFallbackMaterial(0x696969)
    )
    support.position.set(i, 0, -60)
    group.add(support)
  }
  
  // 分支输送带
  const branchConveyor = new THREE.Mesh(
    new THREE.BoxGeometry(3, 2, 60),
    createFallbackMaterial(0x654321)
  )
  branchConveyor.position.set(40, 8, -30)
  group.add(branchConveyor)
  
  return group
}

// 创建办公楼
const createOfficeBuilding = () => {
  const group = new THREE.Group()
  
  // 办公楼主体
  const building = new THREE.Mesh(
    new THREE.BoxGeometry(30, 40, 20),
    createFallbackMaterial(0xDEB887)
  )
  building.position.y = 20
  building.castShadow = true
  group.add(building)
  
  // 创建窗户网格
  for (let floor = 0; floor < 8; floor++) {
    for (let window = 0; window < 6; window++) {
      const windowMesh = new THREE.Mesh(
        new THREE.BoxGeometry(3, 3, 0.5),
        createFallbackMaterial(0x87CEEB)
      )
      windowMesh.position.set(
        (window - 2.5) * 4,
        5 + floor * 4.5,
        10.5
      )
      group.add(windowMesh)
    }
  }
  
  return group
}

// 创建冷却塔
const createCoolingTowers = () => {
  const group = new THREE.Group()
  
  for (let i = 0; i < 2; i++) {
    // 冷却塔主体（双曲面形状）
    const tower = new THREE.Mesh(
      new THREE.CylinderGeometry(12, 18, 50, 16),
      createFallbackMaterial(0xF5F5DC)
    )
    tower.position.set(i * 40, 25, 0)
    tower.castShadow = true
    group.add(tower)
    
    // 冷却塔顶部
    const towerTop = new THREE.Mesh(
      new THREE.CylinderGeometry(10, 12, 5),
      createFallbackMaterial(0xD3D3D3)
    )
    towerTop.position.set(i * 40, 52.5, 0)
    group.add(towerTop)
  }
  
  return group
}

// 创建道路系统
const createRoadSystem = () => {
  const group = new THREE.Group()
  
  // 主干道
  const mainRoad = new THREE.Mesh(
    new THREE.BoxGeometry(300, 0.5, 10),
    createFallbackMaterial(0x404040)
  )
  mainRoad.position.set(0, 0.25, -80)
  group.add(mainRoad)
  
  // 支路
  const sideRoad = new THREE.Mesh(
    new THREE.BoxGeometry(8, 0.5, 200),
    createFallbackMaterial(0x404040)
  )
  sideRoad.position.set(60, 0.25, 0)
  group.add(sideRoad)
  
  // 道路中心线
  const centerLine = new THREE.Mesh(
    new THREE.BoxGeometry(300, 0.1, 0.5),
    createFallbackMaterial(0xFFFF00)
  )
  centerLine.position.set(0, 0.8, -80)
  group.add(centerLine)
  
  return group
}

// 加载单个B3DM文件（修复版本）
const loadB3DMFileFixed = async (path: string, fileName: string) => {
  try {
    debugInfo.value += `\n🔍 正在获取文件: ${fileName}`
    
    // 使用更安全的请求头
    const response = await fetch(path, {
      method: 'GET',
      headers: {
        'Accept': 'application/octet-stream, */*',
        'Cache-Control': 'no-cache'
      },
      mode: 'cors'
    })
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`)
    }
    
    const contentType = response.headers.get('content-type')
    debugInfo.value += `\n📋 文件类型: ${contentType || '未知'}`
    
    const arrayBuffer = await response.arrayBuffer()
    debugInfo.value += `\n📄 文件大小: ${(arrayBuffer.byteLength / 1024 / 1024).toFixed(2)} MB`
    
    // 使用增强的B3DM解析
    const gltf = await parseB3DMFileEnhanced(arrayBuffer, fileName)
    
    // 添加模型到场景
    const model = (gltf as any).scene
    if (!model) {
      throw new Error('模型数据为空')
    }
    
    model.userData.isModel = true
    model.userData.fileName = fileName
    
    // 调整模型位置和大小
    const box = new THREE.Box3().setFromObject(model)
    const size = box.getSize(new THREE.Vector3())
    const center = box.getCenter(new THREE.Vector3())
    
    // 将模型移到原点
    model.position.sub(center)
    
    // 如果模型太大，缩放它
    const maxSize = Math.max(size.x, size.y, size.z)
    if (maxSize > 200) {
      const scale = 200 / maxSize
      model.scale.multiplyScalar(scale)
      debugInfo.value += `\n🔄 模型缩放: ${scale.toFixed(3)}x`
    }
    
    scene.add(model)
    
    debugInfo.value += `\n✅ 模型尺寸: ${Math.round(size.x)}×${Math.round(size.y)}×${Math.round(size.z)}`
    
    // 调整相机查看模型
    const modelBox = new THREE.Box3().setFromObject(model)
    const modelSize = modelBox.getSize(new THREE.Vector3())
    const maxDimension = Math.max(modelSize.x, modelSize.y, modelSize.z)
    const distance = maxDimension * 3
    
    camera.position.set(distance, distance * 0.7, distance)
    camera.lookAt(0, 0, 0)
    controls.target.set(0, 0, 0)
    
  } catch (error: any) {
    console.error(`B3DM文件加载失败 ${fileName}:`, error)
    throw new Error(`${fileName}: ${error.message}`)
  }
}

// 增强的B3DM解析器
const parseB3DMFileEnhanced = async (arrayBuffer: ArrayBuffer, fileName: string) => {
  try {
    const dataView = new DataView(arrayBuffer)
    
    // 检查文件头
    const magic = new TextDecoder('utf-8', { fatal: false }).decode(new Uint8Array(arrayBuffer, 0, 4))
    if (magic !== 'b3dm') {
      throw new Error(`不是有效的B3DM文件，魔数: ${magic}`)
    }

    const version = dataView.getUint32(4, true)
    const byteLength = dataView.getUint32(8, true)
    const featureTableJSONByteLength = dataView.getUint32(12, true)
    const featureTableBinaryByteLength = dataView.getUint32(16, true)
    const batchTableJSONByteLength = dataView.getUint32(20, true)
    const batchTableBinaryByteLength = dataView.getUint32(24, true)

    debugInfo.value += `\n🔍 B3DM版本: ${version}, 总长度: ${byteLength}`

    // 计算GLB数据的起始位置
    const headerLength = 28
    let glbOffset = headerLength + featureTableJSONByteLength + featureTableBinaryByteLength + 
                   batchTableJSONByteLength + batchTableBinaryByteLength
    
    // 字节对齐
    if (glbOffset % 8 !== 0) {
      glbOffset += 8 - (glbOffset % 8)
    }

    if (glbOffset >= arrayBuffer.byteLength) {
      throw new Error(`GLB数据偏移超出文件范围: ${glbOffset} >= ${arrayBuffer.byteLength}`)
    }

    // 提取GLB数据
    const glbData = arrayBuffer.slice(glbOffset)
    debugInfo.value += `\n🔍 GLB数据偏移: ${glbOffset}, 大小: ${glbData.byteLength} bytes`
    
    // 验证GLB数据
    const glbMagic = new TextDecoder('utf-8', { fatal: false }).decode(new Uint8Array(glbData, 0, 4))
    if (glbMagic !== 'glTF') {
      throw new Error(`GLB数据损坏，魔数: ${glbMagic}`)
    }
    
    // 使用GLTFLoader加载GLB数据，增强容错处理
    const loader = new GLTFLoader()
    
    return new Promise((resolve, reject) => {
      // 设置超时
      const timeoutId = setTimeout(() => {
        reject(new Error('加载超时（30秒）'))
      }, 30000)
      
      loader.parse(glbData, '', 
        (gltf) => {
          clearTimeout(timeoutId)
          debugInfo.value += '\n✅ GLB解析成功'
          
          // 检查模型内容
          if (!gltf.scene) {
            reject(new Error('模型不包含场景数据'))
            return
          }
          
          // 统计模型信息
          let meshCount = 0
          let materialCount = 0
          gltf.scene.traverse((child) => {
            if (child instanceof THREE.Mesh) {
              meshCount++
              if (child.material) {
                if (Array.isArray(child.material)) {
                  materialCount += child.material.length
                } else {
                  materialCount++
                }
              }
            }
          })
          
          debugInfo.value += `\n📋 模型统计: ${meshCount} 个mesh, ${materialCount} 个材质`
          
          resolve(gltf)
        }, 
        (error) => {
          clearTimeout(timeoutId)
          debugInfo.value += `\n❌ GLB解析失败: ${error.message}`
          
          // 尝试简化加载
          if (error.message.includes('texture') || error.message.includes('image')) {
            debugInfo.value += '\n🔄 检测到纹理问题，尝试仅加载几何体...'
            // 这里可以实现简化加载逻辑
          }
          
          reject(error)
        }
      )
    })
  } catch (error: any) {
    debugInfo.value += `\n❌ B3DM解析失败: ${error.message}`
    throw error
  }
}

// 测试CORS和文件访问
const testCORSAccess = async () => {
  loading.value = true
  modelInfo.value = '正在测试文件系统访问权限...'
  debugInfo.value = '正在检查Vite开发服务器的静态文件服务'
  
  try {
    const testResults = []
    
    // 测试文件列表
    const testFiles = [
      { path: '/models/ZongHengHP_3dtiles/tileset.json', type: 'JSON' },
      { path: '/models/ZongHengHP_3dtiles/Alpha/tileset.json', type: 'JSON' },
      { path: '/models/ZongHengHP_3dtiles/Alpha/NoLod_2.b3dm', type: 'B3DM' },
      { path: '/models/ZongHengHP_3dtiles/Alpha/NoLod_1.b3dm', type: 'B3DM' },
      { path: '/models/ZongHengHP_3dtiles/Alpha/NoLod_0.b3dm', type: 'B3DM' }
    ]
    
    for (const file of testFiles) {
      try {
        const startTime = performance.now()
        
        // 测试HEAD请求
        const headResponse = await fetch(file.path, { method: 'HEAD' })
        const headTime = performance.now() - startTime
        
        if (headResponse.ok) {
          const contentLength = headResponse.headers.get('content-length')
          const contentType = headResponse.headers.get('content-type')
          const lastModified = headResponse.headers.get('last-modified')
          
          testResults.push(`✅ ${file.path.split('/').pop()}`)
          testResults.push(`   状态: ${headResponse.status} ${headResponse.statusText}`)
          testResults.push(`   大小: ${contentLength ? (parseInt(contentLength) / 1024 / 1024).toFixed(2) + ' MB' : '未知'}`)
          testResults.push(`   类型: ${contentType || '未设置'}`)
          testResults.push(`   响应时间: ${headTime.toFixed(2)}ms`)
          testResults.push(`   修改时间: ${lastModified || '未知'}`)
          
          // 如果是B3DM文件，进行部分内容读取测试
          if (file.type === 'B3DM' && contentLength && parseInt(contentLength) < 10 * 1024 * 1024) { // 小于10MB
            try {
              const getResponse = await fetch(file.path, {
                headers: { 'Range': 'bytes=0-1023' } // 只读取前1KB
              })
              
              if (getResponse.ok || getResponse.status === 206) {
                const partialData = await getResponse.arrayBuffer()
                const magic = new TextDecoder().decode(new Uint8Array(partialData, 0, 4))
                testResults.push(`   B3DM魔数: ${magic === 'b3dm' ? '✅ 正常' : '❌ ' + magic}`)
              }
            } catch (rangeError) {
              testResults.push(`   部分读取: 不支持Range请求`)
            }
          }
          
        } else {
          testResults.push(`❌ ${file.path.split('/').pop()}: ${headResponse.status} ${headResponse.statusText}`)
        }
        
      } catch (error: any) {
        testResults.push(`❌ ${file.path.split('/').pop()}: ${error.message}`)
      }
      
      testResults.push('') // 空行分隔
    }
    
    // 测试网络环境
    testResults.push('🌐 网络环境信息:')
    testResults.push(`   当前域名: ${window.location.origin}`)
    testResults.push(`   协议: ${window.location.protocol}`)
    testResults.push(`   端口: ${window.location.port || '默认'}`)
    testResults.push(`   User-Agent: ${navigator.userAgent.substring(0, 100)}...`)
    
    modelInfo.value = '🔍 文件系统访问测试结果:'
    debugInfo.value = testResults.join('\n')
    
    // 给出建议
    const hasB3DMAccess = testResults.some(r => r.includes('B3DM魔数: ✅'))
    if (hasB3DMAccess) {
      modelInfo.value += '\n\n✅ 文件访问正常，可以尝试加载3D Tiles模型'
    } else {
      modelInfo.value += '\n\n⚠️ 文件访问异常，建议检查文件是否存在或服务器配置'
    }
    
  } catch (error: any) {
    console.error('文件访问测试失败:', error)
    error(`测试失败: ${error?.message || '未知错误'}`)
    modelInfo.value = `❌ 测试失败: ${error?.message || '未知错误'}`
  } finally {
    loading.value = false
  }
}

// 加载测试模型
const loadTestModel = () => {
  // 清除现有模型
  const existingModels = scene.children.filter(child => child.userData.isModel)
  existingModels.forEach(model => scene.remove(model))

  // 创建一个简单的建筑模型
  const group = new THREE.Group()
  group.userData.isModel = true

  // 主建筑体
  const buildingGeometry = new THREE.BoxGeometry(20, 15, 30)
  const buildingMaterial = new THREE.MeshLambertMaterial({ color: 0x8B4513 })
  const building = new THREE.Mesh(buildingGeometry, buildingMaterial)
  building.position.y = 7.5
  building.castShadow = true
  group.add(building)

  // 屋顶
  const roofGeometry = new THREE.ConeGeometry(15, 8, 4)
  const roofMaterial = new THREE.MeshLambertMaterial({ color: 0x654321 })
  const roof = new THREE.Mesh(roofGeometry, roofMaterial)
  roof.position.y = 19
  roof.rotation.y = Math.PI / 4
  roof.castShadow = true
  group.add(roof)

  // 烟囱
  const chimneyGeometry = new THREE.CylinderGeometry(1.5, 1.5, 12)
  const chimneyMaterial = new THREE.MeshLambertMaterial({ color: 0x696969 })
  const chimney = new THREE.Mesh(chimneyGeometry, chimneyMaterial)
  chimney.position.set(8, 21, 12)
  chimney.castShadow = true
  group.add(chimney)

  scene.add(group)
  
  modelInfo.value = '测试钢厂建筑模型加载成功'
  resetCamera()
}

// 处理窗口大小调整
const handleResize = () => {
  if (!canvasContainer.value || !camera || !renderer) return
  
  const width = canvasContainer.value.clientWidth
  const height = canvasContainer.value.clientHeight
  
  camera.aspect = width / height
  camera.updateProjectionMatrix()
  renderer.setSize(width, height)
}

onMounted(() => {
  initThreeJS()
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  if (animationId) {
    cancelAnimationFrame(animationId)
  }
  if (renderer) {
    renderer.dispose()
  }
  window.removeEventListener('resize', handleResize)
})
</script>

<style scoped>
.threejs-model-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: #f5f5f5;
}

.control-panel {
  padding: 10px;
  background: white;
  border-bottom: 1px solid #e4e7ed;
  z-index: 10;
}

.controls {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}

.info-panel {
  margin-top: 10px;
  padding: 8px;
  background: #f0f9ff;
  border-radius: 4px;
  white-space: pre-line;
}

.debug-panel {
  margin-top: 8px;
  padding: 8px;
  background: #fef7e0;
  border-radius: 4px;
  white-space: pre-line;
}

.canvas-container {
  flex: 1;
  position: relative;
  overflow: hidden;
}

.canvas-container canvas {
  display: block;
}
</style>